 package com.hp.bon.sgw.wh.channel.handler;

import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.Constants.MessageType;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.BuzProcessorManager;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.core.channel.SoapChannel;
import com.hp.bon.sgw.core.channel.handler.IAsynCallHandler;
import com.hp.bon.sgw.domain.MessageDetail;
import com.hp.bon.sgw.start.SpringContext;
import com.hp.bon.sgw.threads.MessageDetailCacheManager;
import com.hp.bon.sgw.threads.TaskManager;
import com.hp.bon.sgw.wh.Constants.AliParam;
import com.hp.bon.sgw.wh.bean.tmall.TMallPayBean;
import com.hp.bon.sgw.wh.channel.TMallChannel;
import com.hp.bon.sgw.wh.service.TMallResponseService;
import com.hp.bon.sgw.wh.service.UserResourceConfigService;
import com.hp.bon.sgw.wh.service.WHConfigService;
import com.hp.bon.sgw.wh.util.DateUtil;
import com.hp.bon.sgw.wh.utils.SignUtilsImpl;
import com.hp.bon.sgw.wh.utils.TmallPayUtil;
import com.hp.ocs.diameter.DiameterUtils;
import com.hp.ocs.diameter.message.Message;

import net.sf.json.JSONObject;

/**  
 * @ClassName: TMallPayHandle   
 * @Description: TODO  
 * @author: kaiyang  
 * @date:2015年5月4日 上午11:57:29    
 * 补     充:SGW手机直充响应处理类 
 * @author C.J
 * @date 2017年12月5日 上午9:38:27 
 */
public class TMallPayHandle implements IAsynCallHandler{
	private static final Logger _log = LoggerFactory.getLogger(TaobaoFeeHandle.class);
	private static final String XmlMessage = null;
	private UserResourceConfigService userResourceConfigService ;
	private WHConfigService whConfigService;
	@Override
	public void onCallResult(CallParam callParam) {
		XmlMessage ack = null;
		Object response = null;
		if (callParam.getResponse() != null) {
			response = callParam.getResponse();
		} else if (callParam.getRecvResponse() != null) {
			response = callParam.getRecvResponse();
		}
		_log.info("================callParam.getRetCode():"+callParam.getRetCode());
		if (response == null) {
			_log.info("================response == null");
			int _retcodeTmp = callParam.getRetCode() == 3002 ? 11202 : callParam.getRetCode();
			ack = SoapChannel.createERRAnwser(callParam.getSessionId(),_retcodeTmp, callParam.getResultMsg());
			callParam.setServiceResultCode(_retcodeTmp);//11203
		} else {
			if (response instanceof Message) {// CCA -> XML
				ack = BuzProcessorManager.getInstance().convertMessageToAck(callParam);
			} else if (response instanceof XmlMessage) {
				ack = (XmlMessage) response;
			} else {
				_log.warn("unknown response type:" + callParam.getResponse().getClass().getName());
			}
		}
		try {
			String respXML = convertResponseString((Message)response,callParam.getServiceResultCode());
			if("1".equals(respXML)) {
				return;
			}
			byte[] resp = respXML.getBytes("GBK");
			ack.setLength(resp.length);
			ack.setMsgTime(System.currentTimeMillis());
			printStream.write(resp);
			printStream.close();
			callParam.setResponse(ack);
			if (callParam.getRetCode() == Constants.ResultCode.SUCCESS) {// 成功的消息，请求应答入库
				MessageDetail detail = new MessageDetail();
				detail.setBusinessCallId(callParam.getBussinessCallId());
				detail.setSessionId(callParam.getSessionId());
				detail.setServiceContextId(callParam.getServiceContextId());
				detail.setMessageType(MessageType.WSA);
				detail.setDetails(ack.getDATA());
				detail.setMsgTime(new Date(ack.getMsgTime()));
				detail.setOpType("send");
				detail.setHostId(callParam.getUserName());
				MessageDetailCacheManager.getInstance().add(detail);
			}
			TaskManager.taskProcess(callParam);
			_log.info("http response(taobao) " + respXML);
		} catch (UnsupportedEncodingException e) {
			_log.info("convertResponseString UnsupportedEncodingException error,msg=" + e.getMessage());
		} catch (IOException e) {
			_log.info("convertResponseString IOException,msg=" + e.getMessage());
		}
	}


	private String convertResponseString(Message answer, int serviceResultCode){
		_log.info("TMallpayHandle serviceResultCode = {}",serviceResultCode);
		
		String response = "";	    	
		String coopId = tmallPayBean.getCoopId();
	    String tbOrderNo = tmallPayBean.getTbOrderNo();
		Map<String,String> data = new HashMap<String, String>();
		data.put("tbOrderNo",tbOrderNo);		
		if (serviceResultCode == 571) {     //订单重复
			data.put("coopOrderNo","");
			data.put("coopOrderStatus",TMallChannel.REQUEST_FAIL);
			data.put("coopOrderSnap","ReCharge");
			data.put("coopOrderSuccessTime","");
			data.put("failedCode","0301");
			data.put("failedReason","");
		}else if (serviceResultCode == 501) {//充值号码不存在
			data.put("coopOrderNo","");
			data.put("coopOrderStatus",TMallChannel.STATUS_FAIL);
			data.put("coopOrderSnap","ReCharge");
			data.put("coopOrderSuccessTime","");
			data.put("failedCode","0502");
			data.put("failedReason","");			
		}else if (serviceResultCode == 0){//充值成功
			String jf3_flag = userResourceConfigService.getValue("jf3_flag","");
			String[] avpsArr = TmallPayUtil.getAvpsFromMessage(answer);
			if("1".equals(jf3_flag)) {
				String versionType = getVersionType(avpsArr[2],"0");//传参0 1001类 传1 84210类   返参 1 新 0 旧的
				Element serviceInformation= null;
				XmlMessage req = new XmlMessage(true);
				whConfigService = SpringContext.getApplicationContext().getBean(WHConfigService.class);
				String tmallHostId = whConfigService.getValue(AliParam.tmallHostId, "Alibaba1@027.ctnbc-bon.net");
				String sessionId = DiameterUtils.makeSessionID(tmallHostId);
				req.setIp(jsonObject.getString("IP"));
				req.setMsgTime(System.currentTimeMillis());
				req.setMID(sessionId);
				req.setUID(tmallHostId);
				req.setSIG(null);
				req.setREPTAG(0);
				if("1".equals(versionType)) {
					_log.info("=====进入jf3_flag新流程");
					//新流程  Recharged.jf3
					serviceInformation = DocumentHelper.createElement("Service_Information");
					Element element = serviceInformation.addElement("Channel_Id");
					element.setText("200");
					element = serviceInformation.addElement("Area_Code");
					element.setText(avpsArr[3]);
					element = serviceInformation.addElement("DestinationAttr");
					element.setText("2");
					element = serviceInformation.addElement("Destination_Id");
					element.setText(jsonObject.getString("customer"));
					element = serviceInformation.addElement("Destination_Id_Type");
					element.setText("2");
					element = serviceInformation.addElement("Payment_Amount");
					element.setText(jsonObject.getString("payment_Amount"));
					element = serviceInformation.addElement("RequestAmount");
					element.setText(jsonObject.getString("sum").replace(".", ""));
					element = serviceInformation.addElement("Payment_Method");
					element.setText("11");
					element = serviceInformation.addElement("Paid_Time");
					element.setText(DateUtil.dateTimeToStr(new Date()));
					element = serviceInformation.addElement("Payment_Serial_Nbr");
					element.setText(tbOrderNo);
					element = serviceInformation.addElement("Balance_Type");
					element.setText("0");
					element = serviceInformation.addElement("Eff_Date");
					element.setText(DateUtil.dateTimeToStr(new Date()));
					element = serviceInformation.addElement("Exp_Date");
					element.setText("20371231235959");
					element = serviceInformation.addElement("Bonus_Rows");
					element.setText("0");
					element = serviceInformation.addElement("Bank_code");
					element.setText("ALIBB");
					req.setDATA(serviceInformation.asXML());
					req.setDataElement(serviceInformation);
					req.setSCID("Recharged.jf3@027.ctnbc-bon.net");
				}else {
					_log.info("=====进入jf3_flag旧流程");
					//旧  Recharge.SGW
					serviceInformation = TmallPayUtil.getServiceInfoEle(jsonObject.getString("customer"), jsonObject.getString("bankCode"), tbOrderNo, jsonObject.getString("payment_Amount"), jsonObject.getString("sum"),"0");
					req.setDATA(serviceInformation.asXML());
					req.setDataElement(serviceInformation);
					req.setSCID("Recharge.SGW@027.ctnbc-bon.net");
				}
				jsonObject.put("versionType", versionType);
				TMallPayHandle2 tmallPayHandle = new TMallPayHandle2(printStream,tmallPayBean, tmallResponseService, asynExecutor,tmallRetUrl, pubKeyValue,jsonObject);
				CallParam callParam = new CallParam(req.getMID(),req.getSCID(), req, req.getUID(), tmallPayHandle);
				BuzProcessorManager.getInstance().processRequest(callParam);
				return "1";
			}else {
				if( null == avpsArr ){
					data.put("coopOrderNo","");
					data.put("coopOrderStatus",TMallChannel.STATUS_FAIL);
					data.put("coopOrderSnap","ReCharge");
					data.put("coopOrderSuccessTime","");
					data.put("failedCode","0503");
					data.put("failedReason","");
				}else{
					data.put("coopOrderNo",avpsArr[0]);
					data.put("coopOrderStatus",TMallChannel.STATUS_SUCCESS);
					data.put("coopOrderSnap","ReCharge");
					data.put("coopOrderSuccessTime",avpsArr[1]);
					data.put("failedCode", "");
					data.put("failedReason","");
				}
			}
		}else if( 11203 == serviceResultCode ){
			//By C.J :改造后-天猫调用SGW，SGW调用下游BOSS直充接口(Recharge.SGW)，BOSS响应超时的情况下，直接返回天猫状态为充值中，并不回调天猫的地址
			if( null != answer ){
				String[] avpsArrTimeOut = TmallPayUtil.getAvpsFromMessage(answer);
				if( null == avpsArrTimeOut ){
					data.put("coopOrderNo","");
					data.put("coopOrderStatus","UNDERWAY");//充值中
					data.put("coopOrderSnap","ReCharge");
					data.put("coopOrderSuccessTime","");
				}else{
					data.put("coopOrderNo",avpsArrTimeOut[0]);//响应超时
					data.put("coopOrderStatus","UNDERWAY");//充值中
					data.put("coopOrderSnap","ReCharge");
					data.put("coopOrderSuccessTime",avpsArrTimeOut[1]);
				}
				data.put("failedCode","");
				data.put("failedReason","");
			}else{
				data.put("coopOrderNo","");
				data.put("coopOrderStatus","UNDERWAY");//充值中
				data.put("coopOrderSnap","ReCharge");
				data.put("coopOrderSuccessTime","");
				data.put("failedCode","");
				data.put("failedReason","");
			}
		}else {
			data.put("coopOrderNo","");//充值失败
			data.put("coopOrderStatus",TMallChannel.STATUS_FAIL);
			data.put("coopOrderSnap","ReCharge");
			data.put("coopOrderSuccessTime","");
			data.put("failedCode","0503");
			data.put("failedReason","");
		}
		String status = data.get("coopOrderStatus"); 
		if ( null != status && (status.equals(TMallChannel.STATUS_SUCCESS) || status.equals(TMallChannel.CANCEL) || status.equals(TMallChannel.STATUS_FAIL)) ){
			TreeMap<String,String> paraMap = new TreeMap<String, String>();
			String coopOrderNo = data.get("coopOrderNo");
			paraMap.put("coopId", coopId);
			paraMap.put("tbOrderNo", tbOrderNo);
			paraMap.put("coopOrderNo", coopOrderNo);
			paraMap.put("coopOrderStatus", status);
			if (status.equals(TMallChannel.STATUS_SUCCESS)){
				String coopOrderSnap = data.get("coopOrderSnap");
				String coopOrderSuccessTime = data.get("coopOrderSuccessTime");
				paraMap.put("coopOrderSnap", coopOrderSnap);
				paraMap.put("coopOrderSuccessTime", coopOrderSuccessTime);
			}else if (status.equals(TMallChannel.CANCEL) || status.equals(TMallChannel.STATUS_FAIL)){
				paraMap.put("coopOrderNo", tbOrderNo);
				String failedCode = data.get("failedCode");
				paraMap.put("failedCode",failedCode);
				paraMap.put("failedReason", failedCode);
			}
			String source = "";
			for(Entry<String,String> entry:paraMap.entrySet()){
				source += entry.getKey()+entry.getValue();
			}
			source = source + pubKeyValue;
			String sign = SignUtilsImpl.getTmallSign(source);
			paraMap.put("sign",sign);
			TMallRetTask task = new TMallRetTask(tmallPayBean.getNotifyUrl(), paraMap);
			asynExecutor.execute(task);
		}
		response = tmallResponseService.getResponse(data);
		return response;
	}
	
	private PrintStream printStream;
	private TMallPayBean tmallPayBean;
	private TMallResponseService tmallResponseService;
	private ThreadPoolTaskExecutor asynExecutor;
	private JSONObject jsonObject;
	@SuppressWarnings("unused")
	private String tmallRetUrl;
	private String pubKeyValue;
	
	public TMallPayHandle(PrintStream printStream,TMallPayBean tmallPayBean,TMallResponseService tmallResponseService,ThreadPoolTaskExecutor asynExecutor,String tmallRetUrl,String pubKeyValue,JSONObject jsonObject)
	{
		_log.info("============初始化TMallPayHandle数据========");
		this.printStream = printStream;
        this.tmallPayBean = tmallPayBean;
        this.tmallResponseService = tmallResponseService;
        this.asynExecutor = asynExecutor;
        this.tmallRetUrl = tmallRetUrl;
        this.pubKeyValue = pubKeyValue;
        this.jsonObject = jsonObject;
	}
	
	@Override
	public int getProtocolType() {
		return 0;
	}
	
	/**
	 * 由于计费侧提供的接口协议没变，只是地址调整，割接到3.0的本地网需要调用新的地址
	 * 集团电子发票API接口调整
	 * 获取判断使用的地址
	 * jf3_flag 刷新开关  配置为1则表示启用割接地市判断，配置为0则表示按现有的流程
	 * Jf3_jt_latn_id  割接地市配置项（多个地市用逗号分隔，如果配置项调整为888，则表示全部调用新地址）
	 * resultLanIdStr 区域编码
	 * cityId
	 * jf3_jt_latn_id 是84201这种
		jf3_latn_id是1001 1018 这种
		jf3_area_coee是027 0716 这种
	 */
	private String getVersionType(String cityId,String type) {
		String jf3_flag = userResourceConfigService.getValue("jf3_flag","");////增加刷新开关  ,配置为1则表示启用割接地市判断，配置为0则表示按现有的流程
		String jf3_jt_latn_id = userResourceConfigService.getValue("jf3_jt_latn_id","");
		String jf3_latn_id = userResourceConfigService.getValue("jf3_latn_id","");
		String str;
		if("0".equals(type)) {
			//1001类型
			str = jf3_latn_id;
		}else {
			//84201 类型
			str = jf3_jt_latn_id;
		}
		//1 新流程  0 旧的流程
		if("1".equals(jf3_flag)) {
			if("888".equals(str)) {
				return "1";//新的
			}else {
				String[] split_jt_latn_id = str.split(",");
				for (String string : split_jt_latn_id) {
					if(string.equals(cityId)) {
						//包含,仅区分新旧
						return "1";//新的 Recharged.jf3@027.ctnbc-bon.net
					}
				}
			}
			
		}
		return "0";//旧的 SeverRecharge.SGWPAY@027.ctnbc-bon.net  
	}
}
